#define _CRT_SECURE_NO_WARNINGS

#include "Queue.h"

void QueueInit(Queue* pqueue)
{
	assert(pqueue);
	 pqueue->head = pqueue->tail = NULL;
	 pqueue->size = 0;
}

void QueuePush(Queue* pqueue, QueueDataType val)
{
	assert(pqueue);
	QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
	if (!newnode)
	{
		perror("Failed to malloc a new node:");
		exit(1);
	}
	newnode->val = val;
	newnode->next = NULL;
	pqueue->size++;
	if (NULL == pqueue->head)
	{
		pqueue->head = pqueue->tail = newnode;
	}
	else
	{
		pqueue->tail->next = newnode;
		pqueue->tail = pqueue->tail->next;
	}
}

QueueDataType QueuePop(Queue* pqueue)
{
	assert(pqueue);
	if (pqueue->head == NULL)
	{
		printf("The queue is already empty.\n");
		return;
	}
	QueueNode* temp = pqueue->head;
	if (pqueue->head == pqueue->tail)
	{
		pqueue->tail = NULL;
	}
	QueueDataType ret = pqueue->head->val;
	pqueue->head = pqueue->head->next;
	free(temp);
	pqueue->size--;
	return ret;
}

bool QueueIsEmpty(const Queue* pqueue)
{
	assert(pqueue);
	if (pqueue->head == NULL)
	{
		return true;
	}
	return false;
}

QueueDataType QueueFront(const Queue* pqueue)
{
	assert(pqueue);
	if (pqueue->head == NULL)
	{
		printf("The queue is already empty.\n");
		return 0;
	}
	return pqueue->head->val;
}

QueueDataType QueueBack(const Queue* pqueue)
{
	assert(pqueue);
	if (pqueue->head == NULL)
	{
		printf("The queue is already empty.\n");
		return 0;
	}
	return pqueue->tail->val;
}

int QueueSize(const Queue* pqueue)
{
	//assert(pqueue);
	//int ret = 0;
	//QueueNode* pcurrent = pqueue->head;
	//for (; pcurrent != pqueue->tail; ret++)
	//{
	//	pcurrent = pcurrent->next;
	//}
	//return ret + (int)!QueueIsEmpty(pqueue);
	return pqueue->size;
}

void QueuePrint(const Queue* pqueue)
{
	assert(pqueue);
	QueueNode* pcurrent = pqueue->head;
	if (pqueue->head != NULL)
	{
		printf("(Head) <- ");
	}
	for (; pcurrent != NULL;)
	{
		printf("%d <- ", pcurrent->val);
		pcurrent = pcurrent->next;
	}
	if (pqueue->head != NULL)
	{
		printf("(Tail)\n");
	}
	else
	{
		printf("(NULL)\n");
	}
}

void QueueDestory(Queue* pqueue)
{
	assert(pqueue);
	QueueNode* pcurrent = pqueue->head, * temp = NULL;
	for (; pcurrent;)
	{
		temp = pcurrent;
		pcurrent = pcurrent->next;
		free(temp);
	}
	pqueue->head = pqueue->tail = NULL;
}
